import { BaseModel } from './BaseModel';
import { query } from '../../config/database';

export interface IVersion {
  id: string;
  script_id: string;
  version: string;
  content: string;
  message?: string;
  author?: string;
  created_at: Date;
  parent_version?: string;
  content_hash: string;
}

export interface VersionDiff {
  added: string[];
  removed: string[];
  modified: string[];
}

export class Version extends BaseModel {
  constructor() {
    super('versions');
  }
  
  // 创建新版本
  async createVersion(versionData: {
    script_id: string;
    content: string;
    message?: string;
    author?: string;
    parent_version?: string;
  }): Promise<IVersion> {
    // 生成内容哈希
    const crypto = require('crypto');
    const content_hash = crypto.createHash('sha256').update(versionData.content).digest('hex');
    
    // 获取下一个版本号
    const nextVersion = await this.getNextVersionNumber(versionData.script_id);
    
    const result = await query(
      `INSERT INTO versions (script_id, version, content, message, author, parent_version, content_hash)
       VALUES ($1, $2, $3, $4, $5, $6, $7)
       RETURNING *`,
      [
        versionData.script_id,
        nextVersion,
        versionData.content,
        versionData.message,
        versionData.author,
        versionData.parent_version,
        content_hash
      ]
    );
    
    // 更新脚本的更新时间
    await query(
      `UPDATE scripts SET updated_at = CURRENT_TIMESTAMP WHERE id = $1`,
      [versionData.script_id]
    );
    
    return result.rows[0];
  }
  
  // 获取脚本的版本历史
  async getVersionHistory(scriptId: string, options: {
    limit?: number;
    offset?: number;
  } = {}): Promise<IVersion[]> {
    let sql = `SELECT * FROM versions WHERE script_id = $1 ORDER BY created_at DESC`;
    const params: any[] = [scriptId];
    let paramIndex = 2;
    
    if (options.limit) {
      sql += ` LIMIT $${paramIndex++}`;
      params.push(options.limit);
    }
    
    if (options.offset) {
      sql += ` OFFSET $${paramIndex++}`;
      params.push(options.offset);
    }
    
    const result = await query(sql, params);
    return result.rows;
  }
  
  // 获取特定版本
  async getVersion(scriptId: string, version: string): Promise<IVersion | null> {
    const result = await query(
      'SELECT * FROM versions WHERE script_id = $1 AND version = $2',
      [scriptId, version]
    );
    return result.rows[0] || null;
  }
  
  // 获取最新版本
  async getLatestVersion(scriptId: string): Promise<IVersion | null> {
    const result = await query(
      `SELECT * FROM versions 
       WHERE script_id = $1 
       ORDER BY created_at DESC 
       LIMIT 1`,
      [scriptId]
    );
    return result.rows[0] || null;
  }
  
  // 比较两个版本的差异
  async compareVersions(versionId1: string, versionId2: string): Promise<VersionDiff> {
    const result = await query(
      `SELECT v1.content as content1, v2.content as content2
       FROM versions v1, versions v2
       WHERE v1.id = $1 AND v2.id = $2`,
      [versionId1, versionId2]
    );
    
    if (result.rows.length === 0) {
      throw new Error('版本不存在');
    }
    
    const { content1, content2 } = result.rows[0];
    return this.calculateDiff(content1, content2);
  }
  
  // 检查内容是否已存在（避免重复版本）
  async isContentExists(scriptId: string, contentHash: string): Promise<boolean> {
    const result = await query(
      'SELECT 1 FROM versions WHERE script_id = $1 AND content_hash = $2 LIMIT 1',
      [scriptId, contentHash]
    );
    return result.rows.length > 0;
  }
  
  // 获取版本统计信息
  async getVersionStats(scriptId: string): Promise<{
    total_versions: number;
    first_version_date: Date;
    last_version_date: Date;
    authors: string[];
  }> {
    const result = await query(
      `SELECT 
        COUNT(*) as total_versions,
        MIN(created_at) as first_version_date,
        MAX(created_at) as last_version_date,
        array_agg(DISTINCT author) FILTER (WHERE author IS NOT NULL) as authors
       FROM versions 
       WHERE script_id = $1`,
      [scriptId]
    );
    
    const stats = result.rows[0];
    return {
      total_versions: parseInt(stats.total_versions, 10),
      first_version_date: stats.first_version_date,
      last_version_date: stats.last_version_date,
      authors: stats.authors || []
    };
  }
  
  // 删除脚本的所有版本
  async deleteVersionsByScriptId(scriptId: string): Promise<boolean> {
    const result = await query(
      'DELETE FROM versions WHERE script_id = $1',
      [scriptId]
    );
    return result.rowCount > 0;
  }
  
  // 获取下一个版本号
  private async getNextVersionNumber(scriptId: string): Promise<string> {
    const result = await query(
      `SELECT version FROM versions 
       WHERE script_id = $1 
       ORDER BY created_at DESC 
       LIMIT 1`,
      [scriptId]
    );
    
    if (result.rows.length === 0) {
      return '1.0.0';
    }
    
    const lastVersion = result.rows[0].version;
    const versionParts = lastVersion.split('.').map(Number);
    
    // 增加补丁版本号
    versionParts[2] = (versionParts[2] || 0) + 1;
    
    return versionParts.join('.');
  }
  
  // 计算内容差异
  private calculateDiff(content1: string, content2: string): VersionDiff {
    const lines1 = content1.split('\n');
    const lines2 = content2.split('\n');
    
    const added: string[] = [];
    const removed: string[] = [];
    const modified: string[] = [];
    
    // 简单的行级差异计算
    const maxLines = Math.max(lines1.length, lines2.length);
    
    for (let i = 0; i < maxLines; i++) {
      const line1 = lines1[i];
      const line2 = lines2[i];
      
      if (line1 === undefined && line2 !== undefined) {
        added.push(`+${i + 1}: ${line2}`);
      } else if (line1 !== undefined && line2 === undefined) {
        removed.push(`-${i + 1}: ${line1}`);
      } else if (line1 !== line2) {
        modified.push(`~${i + 1}: ${line1} -> ${line2}`);
      }
    }
    
    return { added, removed, modified };
  }
  
  // 获取版本树（显示版本之间的关系）
  async getVersionTree(scriptId: string): Promise<any[]> {
    const result = await query(
      `WITH RECURSIVE version_tree AS (
        SELECT id, version, parent_version, message, author, created_at, 0 as level
        FROM versions 
        WHERE script_id = $1 AND parent_version IS NULL
        
        UNION ALL
        
        SELECT v.id, v.version, v.parent_version, v.message, v.author, v.created_at, vt.level + 1
        FROM versions v
        INNER JOIN version_tree vt ON v.parent_version = vt.id
        WHERE v.script_id = $1
      )
      SELECT * FROM version_tree ORDER BY created_at ASC`,
      [scriptId]
    );
    
    return result.rows;
  }
}